import tkinter as tk
import pystray
from PIL import Image
import win32gui
import win32process
import win32con
import psutil
from tkinter import ttk
import keyboard
import threading


class WindowController:
    def __init__(self, root):
        self.root = root
        self.root.title("窗口隐藏工具")
        self.root.geometry('300x150')

        self.original_styles = {}
        self.is_visible = True

        self.create_widgets()

        # 创建系统托盘图标
        self.create_tray_icon()

        # 绑定窗口关闭事件
        self.root.protocol("WM_DELETE_WINDOW", self.on_close)

    def create_widgets(self):
        self.process_label = tk.Label(self.root, text="选择进程:")
        self.process_label.pack()

        self.process_dropdown = ttk.Combobox(self.root, state="readonly")
        self.update_process_list()
        self.process_dropdown.pack()

        self.hide_button = tk.Button(self.root, text="隐藏", command=self.hide_process)
        self.hide_button.pack()

        self.restore_button = tk.Button(self.root, text="恢复", command=self.restore_process)
        self.restore_button.pack()

        self.refresh_button = tk.Button(self.root, text="刷新进程列表", command=self.update_process_list)
        self.refresh_button.pack()

        # 设置快捷键
        keyboard.add_hotkey('ctrl+z', self.hide_process)
        keyboard.add_hotkey('ctrl+x', self.restore_process)

    def create_tray_icon(self):
        self.tray_icon = pystray.Icon("Window Hider", Image.open("隐藏.ico"), "窗口隐藏工具")
        self.tray_icon.menu = pystray.Menu(
            pystray.MenuItem("显示/隐藏", self.toggle_window),
            pystray.MenuItem("退出", self.exit_app)
        )
        threading.Thread(target=self.tray_icon.run, daemon=True).start()

    def toggle_window(self):
        if self.is_visible:
            self.root.withdraw()
            self.is_visible = False
        else:
            self.root.deiconify()
            self.root.focus_force()
            self.is_visible = True

    def on_close(self):
        self.root.withdraw()
        self.is_visible = False

    def exit_app(self):
        self.tray_icon.stop()
        self.root.quit()

    def update_process_list(self):
        processes = [proc.info['name'] for proc in psutil.process_iter(['pid', 'name']) if
                     proc.info['name'] is not None]
        self.process_dropdown['values'] = list(set(processes))

    def hide_windows(self, process_name):
        for proc in psutil.process_iter(['pid', 'name']):
            if proc.info['name'] == process_name:
                pid = proc.info['pid']
                self.hide_windows_by_pid(pid)

    def hide_windows_by_pid(self, pid):
        def callback(hwnd, hwnds):
            if win32gui.IsWindowVisible(hwnd):
                _, found_pid = win32process.GetWindowThreadProcessId(hwnd)
                if found_pid == pid:
                    hwnds.append(hwnd)
                    self.original_styles[hwnd] = win32gui.GetWindowLong(hwnd, win32con.GWL_STYLE)
                    win32gui.ShowWindow(hwnd, 0)
                    win32gui.SetWindowLong(hwnd, win32con.GWL_STYLE, self.original_styles[hwnd] & ~win32con.WS_VISIBLE)
            return True

        hwnds = []
        win32gui.EnumWindows(callback, hwnds)

    def restore_windows(self, process_name):
        for proc in psutil.process_iter(['pid', 'name']):
            if proc.info['name'] == process_name:
                pid = proc.info['pid']
                self.restore_windows_by_pid(pid)

    def restore_windows_by_pid(self, pid):
        def callback(hwnd, _):
            _, found_pid = win32process.GetWindowThreadProcessId(hwnd)
            if found_pid == pid:
                original_style = self.original_styles.get(hwnd, None)
                if original_style is not None:
                    win32gui.SetWindowLong(hwnd, win32con.GWL_STYLE, original_style)
                    win32gui.ShowWindow(hwnd, win32con.SW_SHOW)
                    win32gui.RedrawWindow(hwnd, None, None,
                                          win32con.RDW_INVALIDATE | win32con.RDW_UPDATENOW | win32con.RDW_ALLCHILDREN)
            return True

        win32gui.EnumWindows(callback, None)

    def hide_process(self):
        process_name = self.process_dropdown.get()
        if process_name:
            self.hide_windows(process_name)

    def restore_process(self):
        process_name = self.process_dropdown.get()
        if process_name:
            self.restore_windows(process_name)


if __name__ == "__main__":
    root = tk.Tk()
    app = WindowController(root)
    root.mainloop()